"""
Debug module

This module provides a debug call to be used by all other modules.

Last Modified: $Id$

@author: U{Gustavo Sverzut Barbieri <barbieri@gmail.com>}
@license: GNU GPL
@copyright: (C) 2005 Gustavo Sverzut Barbieri
@version: $Rev$
"""





import sys
import threading
import traceback
import time


class Output( object ):
    """Used by the debug function to output data.
    """
    def write( self, text ):
        """Write text."""
        sys.stderr.write( text )
    # write()


    def message_head( self, level ):
        """Called before using message()"""
        if threading.activeCount() > 1:
            self.write( '%s: ' % threading.currentThread().getName() )
    # head()


    def message_tail( self, level ):
        """Called after using message()"""
        self.write( '\n' )
    # tail()


    def message( self, level,  message ):
        """Output message."""
        self.write( message )
    # message()
# Output


class XMLOutput( Output ):
    def __init__( self ):
        self.root_node_out = False

        # keep reference to sys.stderr.write, so we can do the __del__ trick
        self.write = sys.stderr.write
    # __init__()

    def __del__( self ):
        if self.started():
            self.end()
    # __del__()


    def started( self ):
        return self.root_node_out
    # started()


    def start( self ):
        self.write( '\n<debug>\n' )
        self.root_node_out = True
    # start()


    def end( self ):
        self.write( '\n</debug>\n' )
    # end()


    def message_head( self, level ):
        if not self.started():
            self.start()

        self.write( '\t<debugentry level="%s" timestamp="%s"' % \
                    ( level, time.time() ) )
        if threading.activeCount() > 1:
            self.write( ' thread="%s"' % threading.currentThread().getName() )
        self.write( '>\n' )
    # head()


    def message_tail( self, level ):
        self.write( '\n\t</debugentry>\n' )
    # tail()

    def message( self, level,  message ):
        """Output message."""
        self.write( message.replace( "<", "&lt;" ).replace( ">", "&gt;" ) )
    # message()
# XMLOutput


def debug( level, * msgs ):
    debug.lock.acquire()
    try:
        if debug.level >= level:
            out = debug.output
            out.message_head( level )
            msg = out.message
            for m in msgs:
                msg( level, m )
            out.message_tail( level )
    finally:
        debug.lock.release()
# debug()
debug.level  = 0
debug.lock   = threading.RLock()
debug.output = Output()


try:
    format_exc = traceback.format_exc
except AttributeError:
    # Python < 2.4 doesn't support format_exc(), create it:
    def format_exc( limit=None ):
        return "".join( traceback.format_exception( * sys.exc_info() ) )
    # format_exc()
    traceback.format_exc = format_exc
